package com.pucong.gitee.database.backup.business.sys.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pucong.gitee.database.backup.business.sys.mapper.SysUserInfoMapper;
import com.pucong.gitee.database.backup.common.entity.sys.*;
import com.pucong.gitee.database.backup.common.entity.sys.dto.SysUserSettingUpdateDto;
import com.pucong.gitee.database.backup.common.entity.sys.jwt.CheckResult;
import com.pucong.gitee.database.backup.common.selfenum.UserStatusEnum;
import com.pucong.gitee.database.backup.configuration.exception.BusinessException;
import com.pucong.gitee.database.backup.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
public class SysLoginServiceImpl implements SysLoginService{

    @Autowired
    private SysUserInfoMapper sysUserInfoMapper;

    @Override
    public Boolean isLogin() {
        String user_token = JwtUtils.getToken();
        if (StringUtils.isNotBlank(user_token)) {
            // 校验token
            CheckResult checkResult = JwtUtils.validateJWT(user_token);
            if (checkResult.isSuccess()) {
                // 获取用户信息
                String subject = checkResult.getClaims().getSubject();
                ObjectMapper objectMapper = new ObjectMapper();
                UserJwt loginUser = null;
                try {
                    loginUser = objectMapper.readValue(subject, UserJwt.class);
                } catch (JsonProcessingException e) {
                    throw new BusinessException("反序列化用户数据失败");
                }
                SysUserInfo sysUserInfo = sysUserInfoMapper.selectById(loginUser.getUuid());
                Date date = sysUserInfo.getLastLoginTime();
                if(date == null || date.getTime() != loginUser.getLastLoginTime().getTime()){
                    return false;
                }
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    @Override
    public UserJwt getLoginUser() {
        UserJwt loginUser = UserRequest.getLoginUser();
        return loginUser;
    }

    @Override
    public UserJwt login(UserLoginVo userLoginVo) {
        // 加密密码
        String password = AESEncryptUtil.encrypt(userLoginVo.getPassword());
        // 获取账号密码
        LambdaQueryWrapper<SysUserInfo> params = new LambdaQueryWrapper<>();
        params.eq(SysUserInfo::getLoginName,userLoginVo.getLoginName());
        params.eq(SysUserInfo::getPassword,password);
        SysUserInfo sysUserInfo = sysUserInfoMapper.selectOne(params);
        if(sysUserInfo == null){
            throw new BusinessException("登录用户名密码错误");
        }
        if (sysUserInfo.getStatus() == UserStatusEnum.正常) {
            // 获取token
            UserJwt userJwt = new UserJwt(sysUserInfo);
            userJwt.setLastLoginTime(new Date());
            String token = this.createToken(userJwt);
            userJwt.setToken(token);
            // 设置请求
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            ObjectMapper objectMapper = new ObjectMapper();
            String userJson = "";
            try {
                userJson = objectMapper.writeValueAsString(userJwt);
            } catch (JsonProcessingException e) {
                throw new BusinessException("登录用户名密码错误");
            }
            // 修改上次登录时间
            SysUserInfo updateTime = new SysUserInfo();
            updateTime.setUuid(userJwt.getUuid());
            updateTime.setLastLoginTime(userJwt.getLastLoginTime());
            sysUserInfoMapper.updateById(updateTime);
            request.setAttribute(SystemConstant.JWT_TOKEN,userJson);
            request.setAttribute(SystemConstant.REQUEST_USER_GET_NAME,token);
            return userJwt;
        } else if (sysUserInfo.getStatus() == UserStatusEnum.过期) {
            throw new BusinessException("账号已过期");
        } else if (sysUserInfo.getStatus() == UserStatusEnum.锁定) {
            throw new BusinessException("账号已被锁定");
        }else{
            throw new BusinessException("账号异常");
        }
    }

    @Override
    public SysReturnUrl loginOut() {
        UserJwt loginUser = UserRequest.getLoginUser();
        // 清理头部的token
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        request.removeAttribute(SystemConstant.JWT_TOKEN);
        request.removeAttribute(SystemConstant.REQUEST_USER_GET_NAME);
        // 设置返回信息
        SysReturnUrl url = new SysReturnUrl();
        url.setLssoUrl(SystemConstant.SYS_LOGIN_PATH);
        return url;
    }

    @Override
    public SysReturnUrl updateUserPwd(UserUpdatePwdVo userUpdatePwdVo) {
        UserJwt loginUser = UserRequest.getLoginUser();
        // 加密密码
        String password = AESEncryptUtil.encrypt(userUpdatePwdVo.getPasswordNew());
        // 校验
        LambdaQueryWrapper<SysUserInfo> params = new LambdaQueryWrapper<>();
        params.eq(SysUserInfo::getLoginName,loginUser.getLoginName());
        params.eq(SysUserInfo::getPassword,userUpdatePwdVo.getPasswordOld());
        SysUserInfo sysUserInfo = sysUserInfoMapper.selectOne(params);
        if(sysUserInfo == null){
            throw new BusinessException("旧密码错误");
        }
        // 修改密码
        SysUserInfo userUpdate = new SysUserInfo();
        userUpdate.setUuid(sysUserInfo.getUuid());
        userUpdate.setPassword(password);
        sysUserInfoMapper.updateById(userUpdate);
        // 退出登录
        SysReturnUrl sysReturnUrl = this.loginOut();
        return sysReturnUrl;
    }

    @Override
    public String createToken(UserJwt userJwt) {
        ObjectMapper objectMapper = new ObjectMapper();
        String userJson = null;
        try {
            userJson = objectMapper.writeValueAsString(userJwt);
        } catch (JsonProcessingException e) {
            throw new BusinessException("序列化用户数据失败");
        }

        String tokenId = userJwt.getUuid() + "_" + ApplicationContextUtil.getResponseHost();
        String token = JwtUtils.createJWT(tokenId, userJson, SystemConstant.TOKEN_EXPIRATION_TIME * 60 * 1000L);
        return token;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateUserSetting(List<SysUserSettingUpdateDto> systemUserSettingUpdateDtoList) {
        UserJwt loginUser = UserRequest.getLoginUser();
        SysUserInfo systemUser = sysUserInfoMapper.selectById(loginUser.getUuid());
        String userSetting = systemUser.getUserSetting();
        if(StringUtils.isBlank(userSetting)){
            userSetting = "{}";
        }
        JSONObject object = JSONObject.parseObject(userSetting);
        for (SysUserSettingUpdateDto sysUserSettingUpdateDto : systemUserSettingUpdateDtoList) {
            object.put(sysUserSettingUpdateDto.getCode(), sysUserSettingUpdateDto.getValue());
        }
        SysUserInfo systemUserUpdate = new SysUserInfo();
        systemUserUpdate.setUuid(loginUser.getUuid());
        systemUserUpdate.setUserSetting(JSONObject.toJSONString(object));
        sysUserInfoMapper.updateById(systemUserUpdate);
    }

    @Override
    public String getLoginUserSetting() {
        final UserJwt loginUser = UserRequest.getLoginUser();
        SysUserInfo sysUserInfo = sysUserInfoMapper.selectById(loginUser.getUuid());
        return sysUserInfo.getUserSetting();
    }
}
